﻿using LightCAD.Runtime;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection.Emit;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace LightCAD.Runtime
{
    public class InputResult
    {
        public object Value { get; set; }
        public string Option { get; set; }
        public object Extent { get; set; }
        public bool IsCancelled { get; set; }
        public InputResult()
        {
        }
        public InputResult(object value, string option)
        {
            Value = value;
            Option = option;
        }
        public InputResult(object value, string option, object extent)
        {
            this.Value = value;
            this.Option = option;
            this.Extent = extent;
        }

    }
    public class Inputer
    {
        protected CancellationTokenSource cts;
        protected bool isInputed;
        public bool isCancelled;
        protected DocumentRuntime docRt;
        protected ViewportRuntime vportRt;

        protected Inputer(DocumentRuntime docRt)
        {
            this.docRt = docRt;
            this.vportRt = this.docRt.DrawingEditRt.ActiveViewportRt;
        }
        protected void AttachEvents()
        {
            docRt.DrawingEditRt.ActiveViewportRt.Control.AttachEvents(
               this.OnViewportMouseEvent, this.OnViewportKeyDown,null, null, null
            );
            docRt.CommandCtrl.AttachInputEvent(OnInputBoxKeyDown, OnInputBoxKeyUp);
        }



        protected void DetachEvents()
        {
            docRt.DrawingEditRt.ActiveViewportRt.Control.DetachEvents(
                this.OnViewportMouseEvent, this.OnViewportKeyDown,null, null, null
             );

            docRt.CommandCtrl.DetachInputEvent(OnInputBoxKeyDown, OnInputBoxKeyUp);

        }

        protected virtual void OnViewportMouseEvent(string type, MouseEventRuntime e)
        {
            if (type == "Down") OnViewportMouseDown(e);
            else if (type == "Move") OnViewportMouseMove(e);
            else if (type == "Up") OnViewportMouseUp(e);
            else if (type == "Wheel") OnViewportMouseWheel(e);
            else if (type == "HoverStart") OnViewportMouseHoverStart(e);
            else if (type == "HoverEnd") OnViewportMouseHoverEnd(e);
        }
        protected virtual void OnViewportMouseHoverStart(MouseEventRuntime e)
        {
        }
        protected virtual void OnViewportMouseHoverEnd(MouseEventRuntime e)
        {
        }
        protected virtual void OnViewportMouseDown(MouseEventRuntime e)
        {
        }
        protected virtual void OnViewportMouseMove(MouseEventRuntime e)
        {
        }
        protected virtual void OnViewportMouseUp(MouseEventRuntime e)
        {
        }
        protected virtual void OnViewportMouseWheel(MouseEventRuntime e)
        {
        }
        protected virtual void OnViewportKeyDown(KeyEventRuntime e)
        {
             if(e.KeyCode == 27 || e.KeyCode==13 || e.KeyCode == 32)//Escape /Enter /Space
            {
                OnInputBoxKeyDown(new KeyEventRuntime { KeyCode=e.KeyCode, KeyModifiers=e.KeyModifiers });
            }
        }
        protected virtual void OnInputBoxKeyDown(KeyEventRuntime e)
        {
            if (e.KeyCode == 27)//Keys.Escape
            {
                this.Cancel();
            }
            else if (e.KeyCode == 13 || e.KeyCode == 32) 
            {
                var text = docRt.CommandCtrl.GetInputText().Trim();
                var prompt = docRt.CommandCtrl.GetPrompt().Trim();
                WriteInfo(prompt, text);
            }
        }
        protected virtual void OnInputBoxKeyUp(KeyEventRuntime e)
        {
        }
        protected async Task WaitFinish()
        {
            cts = new CancellationTokenSource();
            await Task.Run(() =>
            {
                while (!cts.Token.IsCancellationRequested && !isInputed)
                {
                }
            }, cts.Token);
        }

        protected void Finish()
        {
            this.isInputed = true;
        }
        protected void Cancel()
        {
            this.isCancelled = true;
            this.cts.Cancel();
        }
        public void Prompt(string prompt)
        {
            this.docRt.CommandCtrl.Prompt(prompt);
        }
        public void WriteInfo(string prompt,string input = "", string result="")
        {
            this.docRt.CommandCtrl.WriteInfo(prompt+ input + result);
        }
        public void Reset()
        {
            this.isCancelled = false;
            this.isInputed = false;
        }
    }
}
